package com.unswift.cloud.adapter.system.api;

import java.io.InputStreamReader;
import java.lang.reflect.Modifier;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiEntity;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;
import com.unswift.cloud.adapter.BaseAdapter;
import com.unswift.cloud.mapper.system.api.classes.SystemApiClassExtendMapper;
import com.unswift.cloud.mapper.system.api.classes.SystemApiClassMapper;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassDataDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassInsertDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassSearchDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassSingleDo;
import com.unswift.cloud.pojo.dao.system.api.classes.SystemApiClassUpdateDo;
import com.unswift.utils.ClassUtils;
import com.unswift.utils.DateUtils;
import com.unswift.utils.EncryptionUtils;
import com.unswift.utils.ExceptionUtils;
import com.unswift.utils.FileUtils;
import com.unswift.utils.ObjectUtils;
import com.unswift.utils.StringUtils;

@Component
@Api(value="类api公共服务-此bean可以被任何Service引用", author="unswift", date="2023-09-06", version="1.0.0")
public class SystemApiClassAdapter extends BaseAdapter{
	
	@Autowired
	@ApiField("类api数据库操作对象")
	private SystemApiClassMapper systemApiClassMapper;
	
	@Autowired
	@ApiField("类api数据库扩展操作对象")
	private SystemApiClassExtendMapper systemApiClassExtendMapper;
	
	@ApiField("微服务名称")
	@Value("${spring.application.name}")
	private String serverName;
	
	@ApiMethod(value="获取类api数据库操作对象", returns=@ApiField("数据库操作对象"))
	public SystemApiClassMapper getMapper(){
		return systemApiClassMapper;
	}
	
	@ApiMethod(value="获取类api模块名称", returns=@ApiField("模块名称"))
	public String getModule(){
		return "systemApiClass";
	}
	
	@ApiMethod(value="根据主键查询单个对象", params=@ApiField("主键"), returns=@ApiField("主键匹配的对象"))
	public SystemApiClassDataDo findById(Long id){
		return this.findSingle(new SystemApiClassSingleDo(id, null));
	}
	
	@ApiMethod(value="根据主键列表查询列表对象", params=@ApiField("主键列表"), returns=@ApiField("主键列表匹配的列表对象"))
	public List<SystemApiClassDataDo> findByIds(List<Long> idList){
		return this.findList(new SystemApiClassSearchDo(idList));
	}
	
	@ApiMethod(value="根据查询对象查询首个对象", params={@ApiField("查询对象"), @ApiField("查询到多个是否抛出异常，可以传入指定提示语，如果提示语为空，则不提示，总的提示与格式：根据%s查询到多条数据，只需要传递%s部分即可")}, returns=@ApiField("首个对象"))
	public SystemApiClassDataDo findFirst(SystemApiClassSearchDo search, String multipleException){
		List<SystemApiClassDataDo> list=this.findList(search);
		if(ObjectUtils.isEmpty(list)){
			return null;
		}
		if(ObjectUtils.isNotEmpty(multipleException)){
			ExceptionUtils.trueException(list.size()>1, "multiple.data.found", multipleException);
		}
		return list.get(0);
	}
	
    @ApiMethod(value="根据api注解解析出数据库对象", params = {@ApiField("Api注解"), @ApiField("api注解的类类型")})
    public SystemApiClassInsertDo handleApiAnno(Api apiAnno, Class<?> apiClass) {
    	String signature=EncryptionUtils.md5Hex(FileUtils.reader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(apiClass.getName().replace(".", "/")+".class")), true));
    	String className = ClassUtils.getClassStatement(apiClass, null);
        SystemApiClassSearchDo search=new SystemApiClassSearchDo();
        search.setServer(serverName);
        search.setClassStatement(className);
        SystemApiClassDataDo existsClass = this.findFirst(search, String.format("类‘%s’", className));
        SystemApiClassInsertDo insert;
        if(ObjectUtils.isEmpty(existsClass)) {
    		insert=new SystemApiClassInsertDo();
            if(apiClass.isInterface()) {
                insert.setClassType("interface");
            }else if(apiClass.isEnum()) {
                insert.setClassType("enum");
            }else if(apiClass.isAnnotation()){
            	insert.setClassType("annotation");
            }else {
                insert.setClassType("class");
            }
            insert.setServer(serverName);
            insert.setModifiers(Modifier.toString(apiClass.getModifiers()));
    		insert.setClassName(StringUtils.join(apiAnno.value(), "、"));
            insert.setClassStatement(className);
            insert.setClassDescribe(StringUtils.join(apiAnno.describe(), "<br>"));
            insert.setAuthor(apiAnno.author());
            insert.setDate(DateUtils.parse(apiAnno.date(), "yyyy-MM-dd"));
            insert.setVersion(apiAnno.version());
            insert.setDeprecated(ObjectUtils.isNotEmpty(apiClass.getAnnotation(Deprecated.class)));
            insert.setSuperClass(ClassUtils.getSuperClassStatement(apiClass));
            insert.setInterfaces(ClassUtils.getInterfacesClassStatement(apiClass));
            insert.setClassSignature(signature);
            insert.setIsChange(true);
            this.save(insert, false);
    	}else {
    		insert=new SystemApiClassInsertDo();
    		this.convertPojo(existsClass, insert);
    		if(signature.equals(existsClass.getClassSignature())) {
    			insert.setIsChange(false);
    		}else {
    			insert.setIsChange(true);
    			SystemApiClassUpdateDo update=new SystemApiClassUpdateDo();
    			update.setId(existsClass.getId());
    			if(apiClass.isInterface()) {
                    insert.setClassType("interface");
                }else if(apiClass.isEnum()) {
                    insert.setClassType("enum");
                }else if(apiClass.isAnnotation()){
                	insert.setClassType("annotation");
                }else {
                    insert.setClassType("class");
                }
    			update.setModifiers(Modifier.toString(apiClass.getModifiers()));
    			update.setClassName(StringUtils.join(apiAnno.value(), "、"));
    			update.setClassStatement(className);
    			update.setClassDescribe(StringUtils.join(apiAnno.describe(), "<br>"));
    			update.setAuthor(apiAnno.author());
    			update.setDate(DateUtils.parse(apiAnno.date(), "yyyy-MM-dd"));
    			update.setVersion(apiAnno.version());
    			update.setDeprecated(ObjectUtils.isNotEmpty(apiClass.getAnnotation(Deprecated.class)));
    			update.setSuperClass(ClassUtils.getSuperClassStatement(apiClass));
    			update.setInterfaces(ClassUtils.getInterfacesClassStatement(apiClass));
    			update.setClassSignature(signature);
    			this.update(update, false);
    		}
    	}
        return insert;
    }
    
    @ApiMethod(value="根据api实体注解解析出数据库对象", params = {@ApiField("Api实体注解"), @ApiField("api实体注解的类类型")})
    public SystemApiClassInsertDo handleApiAnno(ApiEntity apiAnno, Class<?> apiClass) {
    	String signature=EncryptionUtils.md5Hex(FileUtils.reader(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(apiClass.getName().replace(".", "/")+".class")), true));
    	String className = ClassUtils.getClassStatement(apiClass, null);
    	SystemApiClassSearchDo search=new SystemApiClassSearchDo();
        search.setServer(serverName);
        search.setClassStatement(className);
        SystemApiClassDataDo existsClass = this.findFirst(search, String.format("类‘%s’", className));
        SystemApiClassInsertDo insert;
        if(ObjectUtils.isEmpty(existsClass)) {
	    	insert=new SystemApiClassInsertDo();
	        insert.setClassType("entity");
	        insert.setServer(serverName);
	        insert.setModifiers(Modifier.toString(apiClass.getModifiers()));
	        insert.setClassName(StringUtils.join(apiAnno.value(), "、"));
            insert.setClassStatement(className);
            insert.setClassDescribe(StringUtils.join(apiAnno.describe(), "<br>"));
	        insert.setAuthor(apiAnno.author());
	        insert.setDate(DateUtils.parse(apiAnno.date(), "yyyy-MM-dd"));
	        insert.setVersion(apiAnno.version());
	        insert.setDeprecated(ObjectUtils.isNotEmpty(apiClass.getAnnotation(Deprecated.class)));
	        insert.setSuperClass(ClassUtils.getSuperClassStatement(apiClass));
	        insert.setInterfaces(ClassUtils.getInterfacesClassStatement(apiClass));
	        insert.setClassSignature(signature);
            insert.setIsChange(true);
	        this.save(insert, false);
        }else {
    		insert=new SystemApiClassInsertDo();
    		this.convertPojo(existsClass, insert);
    		if(signature.equals(existsClass.getClassSignature())) {
    			insert.setIsChange(false);
    		}else {
    			insert.setIsChange(true);
    			SystemApiClassUpdateDo update=new SystemApiClassUpdateDo();
    			update.setId(existsClass.getId());
    			update.setClassType("entity");
    			update.setModifiers(Modifier.toString(apiClass.getModifiers()));
    			update.setClassName(StringUtils.join(apiAnno.value(), "、"));
    			update.setClassStatement(className);
    			update.setClassDescribe(StringUtils.join(apiAnno.describe(), "<br>"));
    			update.setAuthor(apiAnno.author());
    			update.setDate(DateUtils.parse(apiAnno.date(), "yyyy-MM-dd"));
    			update.setVersion(apiAnno.version());
    			update.setDeprecated(ObjectUtils.isNotEmpty(apiClass.getAnnotation(Deprecated.class)));
    			update.setSuperClass(ClassUtils.getSuperClassStatement(apiClass));
    			update.setInterfaces(ClassUtils.getInterfacesClassStatement(apiClass));
    			update.setClassSignature(signature);
    			this.update(update, false);
    		}
    	}
        return insert;
    }
}
